

package AddressBook.Controller;

import AddressBook.Model.*;
import AddressBook.Model.Exception.InvalidFileExtensionException;
import AddressBook.Model.Exception.KeyAlreadyUsedHashMapException;
import AddressBook.Model.Exception.NoSuchKeyFoundHashMapException;
import AddressBook.View.*;
import AddressBook.View.Dialog.AddContactDialog;
import AddressBook.View.Dialog.MyFileChooser;
import AddressBook.View.Dialog.MyInputDialog;

import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import java.io.*;
import java.util.ArrayList;


/**
 * The Class SwingController provides function to manage events received from the MainView
 */
public class SwingController {
    /**
     * This field stores a reference of the view
     */
    private MainView view;
    /**
     * This field stores a reference of the model
     */
    private GroupManager model;

    /**
     * This field stores a reference of the fileManager
     */
    private FileManager fileManager;

    /**
     * This Constructor create and initialize the SwingController's object with the specified view and model
     *
     * @param model The desired model
     * @param view  The desired view
     */
    public SwingController(GroupManager model, MainView view) {
        this.model = model;
        this.view = view;

        view.setController(this);

        fileManager = new FileManager();
        processLoadingRequest(new File("contactsList.csv"));
        try {
            attachWindowsClosingListener();
            attachActionFileMenuListener();
            attachListenerEditMenu();

            attachActionListenerSearchbar();
        } catch (Exception n) {
            n.printStackTrace();

        }

    }

    /**
     * This method allows to define the different actions performed when the object received a loading request
     *
     * @param selectedFile The file to load
     */
    private void processLoadingRequest(File selectedFile) {
        try {

            String filename = selectedFile.getName();
            String extension = filename.substring(filename.lastIndexOf("."));

            ArrayList<Contact> contactList;
            if (extension.equals(AuthorizedFileExtension.getDottedCsvExtension()))
                contactList = fileManager.load(selectedFile);
            else if (extension.equals(AuthorizedFileExtension.getDottedSerExtension()))
                contactList = fileManager.deserializeItemList(selectedFile);
            else throw new InvalidFileExtensionException("Invalid file extension");

            model.splitContactPerGroup(contactList);
            view.displayAllContacts();
            initGroupSelector();
            view.setEnabledSearchBar(true);

        } catch (FileNotFoundException n) {
            view.showErrorDialog(n.getMessage());
        } catch (EOFException n) {
            view.showErrorDialog(n.getMessage());
        } catch (IOException n) {
            view.showErrorDialog(n.getMessage());
        } catch (ClassNotFoundException n) {
            view.showErrorDialog(n.getMessage());
        } catch (InvalidFileExtensionException n) {
            view.showErrorDialog(n.getMessage());
        } catch (KeyAlreadyUsedHashMapException n) {
            view.showErrorDialog(n.getMessage());
        }
    }

    /**
     * This method allows to define the different actions performed when the object received a saving request
     *
     * @param selectedFile The file to save
     */
    private void processSavingRequest(File selectedFile) {
        try {
            String filename = selectedFile.getName();
            String extension = filename.substring(filename.lastIndexOf("."));

            if (extension.equals(AuthorizedFileExtension.getDottedCsvExtension()))
                fileManager.save(selectedFile, model.getContactList());
            else if (extension.equals(AuthorizedFileExtension.getDottedSerExtension()))
                fileManager.serializeItemList(selectedFile, model.getContactList());
            else throw new InvalidFileExtensionException("Invalid file extension");

        } catch (IOException n) {
            view.showErrorDialog(n.getMessage());
        } catch (InvalidFileExtensionException n) {
            view.showErrorDialog(n.getMessage());
        }
    }

    /**
     * This method allows to attach and define an action listener to the open menu contact
     */
    private void attachActionFileMenuListener() {
        MyMenuBar menuBar = view.getMyMenuBar();

        menuBar.addListenerOpenMenu(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                view.displayFileLoader();
            }
        });

        menuBar.addListenerSaveFileMenu(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                view.displayFileSaver();
            }
        });

        menuBar.addListenerExitMenu(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                System.exit(0);
            }
        });

        attachActionListenerFileChooser();

    }

    /**
     * This method allows to attach and define a windows listener to the main view
     */
    private void attachWindowsClosingListener() {
        view.addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                super.windowClosing(e);    //To change body of overridden methods use File | Settings | File Templates.
                System.exit(0);
            }
        });
    }

    /**
     * This method allows to attach and define an action listener to the fileChooser
     */
    private void attachActionListenerFileChooser() {
        view.addActionlistenerFileChooser(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                String command = e.getActionCommand();
                MyFileChooser src = (MyFileChooser) e.getSource();

                if (command.equals(JFileChooser.APPROVE_SELECTION))
                    if (src.getCurrentState().equals(MyFileChooser.State.OPEN_DIALOG)) {

                        File selectedFile = src.getSelectedFile();

                        processLoadingRequest(selectedFile);

                    } else {

                        File fileToSave = src.getSelectedFile();

                        processSavingRequest(fileToSave);

                    }

                src.resetState();
            }
        });
    }

    /**
     * This method allows to attach and define an action listener to the combobox
     */
    private void attachActionListenerSearchbar() {
        view.addActionListenerMyComboBox(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                JComboBox src = (JComboBox) e.getSource();
                Object selectedItem = src.getSelectedItem();
                if (selectedItem instanceof Group)
                    view.displaySpecifiedFamily((Group) src.getSelectedItem());
                else {
                    if (selectedItem instanceof Contact)
                        view.displaySpecifiedItem((Contact) selectedItem);

                    else view.displayAllContacts();
                }
            }
        });
    }


    /**
     * This method allows to define the different actions performed when the object received a add contact request
     */
    private void attachListenerAddItemView() {
        AddContactDialog addView = view.getAddContactDialog();

        addView.addActionListenerAddButton(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {

                AddContactDialog addView = view.getAddContactDialog();

                Contact tmp = new Contact();
                if (!addView.getFirstNameField().isEmpty()) {
                    tmp.setFirstName(addView.getFirstNameField());

                    if (!addView.getLastNameField().isEmpty()) {
                        tmp.setLastName(addView.getLastNameField());

                        tmp.setGroup(addView.getGroupField());

                        if (!addView.getHomeAddressField().isEmpty()) {
                            tmp.setHomeAddress(addView.getHomeAddressField());
                            if (!addView.getCompagnyAddessField().isEmpty()) {
                                tmp.setCompagnyAddress(addView.getCompagnyAddessField());
                                if (!addView.getPersonalPhoneField().isEmpty()) {
                                    tmp.setPersonalPhone(addView.getPersonalPhoneField());
                                    if (!addView.getProfessionalPhoneField().isEmpty()) {
                                        tmp.setProfessionalPhone(addView.getProfessionalPhoneField());
                                        if (!addView.getHomePageField().isEmpty()) {
                                            tmp.setHomePage(addView.getHomePageField());
                                            if (!addView.getEmailField().isEmpty()) {
                                                tmp.setEmail(addView.getEmailField());
                                                if (!addView.getUriPhotoField().isEmpty()) {
                                                    tmp.setUriPicture(addView.getUriPhotoField());
                                                    try {
                                                        model.addContact(tmp);
                                                        addView.dispose();
                                                        view.initializeDataSearchBar();
                                                        addView.resetAllField();
                                                        view.displayAllContacts();
                                                        addView.resetAllField();
                                                    } catch (Exception n) {
                                                        view.showErrorDialog(n.getMessage());
                                                    }
                                                } else view.showErrorDialog(AddContactDialog.URIPHOTO_FIELD_IS_EMPTY);
                                            } else view.showErrorDialog(AddContactDialog.EMAIL_FIELD_IS_EMPTY);
                                        } else view.showErrorDialog(AddContactDialog.HOMEPAGE_FIELD_IS_EMPTY);
                                    } else view.showErrorDialog(AddContactDialog.PROFESSIONALPHONE_FIELD_IS_EMPTY);
                                } else view.showErrorDialog(AddContactDialog.PERSONALPHONE_FIELD_IS_EMPTY);
                            } else view.showErrorDialog(AddContactDialog.COMPAGNYADDRESS_FIELD_IS_EMPTY);
                        } else view.showErrorDialog(AddContactDialog.HOMEADDRESS_FIELD_IS_EMPTY);
                    } else view.showErrorDialog(AddContactDialog.LASTNAME_FIELD_IS_EMPTY);
                } else view.showErrorDialog(AddContactDialog.FIRSTNAME_FIELD_IS_EMPTY);
            }
        });

        addView.addActionListenerCancelButton(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                view.getAddContactDialog().dispose();
            }
        });
    }

    /**
     * This method allows to define the different actions performed when the object received a edit menu request
     */
    private void attachListenerEditMenu() {
        MyMenuBar menuBar = view.getMyMenuBar();

        menuBar.addListenerAddItemEditMenu(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                view.showAddDialog();

            }
        });

        menuBar.addListenerRemoveItemEditMenu(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                view.showInputDialogRemoveItem();
            }
        });

        attachListenerAddItemView();
        attachListenerRemoveItemView();
    }

    /**
     * This method allows to define the different actions performed when the object received a remove contact request
     */
    private void attachListenerRemoveItemView() {
        MyInputDialog dialog = view.getRemoveItemDialog();
        dialog.addActionListenerValidButton(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                MyInputDialog dialog = view.getRemoveItemDialog();
                Contact selectedContact = (Contact) dialog.getSelectedObjectMyComboBox();
                try {
                    model.removeContact(selectedContact);
                    view.initializeDataSearchBar();

                } catch (NoSuchKeyFoundHashMapException n) {
                    view.showErrorDialog(n.getMessage());
                }
                view.displayAllContacts();
                dialog.dispose();
            }
        });
        dialog.addActionListenerCancelButton(new ActionListener() {
            @Override
            public void actionPerformed(ActionEvent e) {
                view.getRemoveItemDialog().dispose();
            }
        });

    }

    public void initGroupSelector() {
        view.initializeDataSearchBar();
        view.getAddContactDialog().setGroupField(model.getGroupArray());
    }
}




